<template>
	<XConfigProvider>

		<el-upload
			v-model:file-list="fileArray"
			style="width: 100%"
			v-bind="$attrs"
			:before-upload="beforeUpload"
			:class="fileArray.length >= ($attrs['limit'] as number) ? 'x-hiddeUpload' : ''"
			:http-request="(file: any) => httpRequest($attrs['http-request'], file)"
		>
			<template #trigger>
				<div
					v-if="$attrs&&($attrs!['list-type']==='picture-card')"
					class="x-avatar"
				>
					<img src="../images/circle-plus.png" alt="" />
					{{ $attrs.disabled ? '正在上传中' : text || '上传图片' }}
				</div>
				<el-button
					v-else-if="$attrs.isButton"
					type="primary"
					plain
					:disabled="($attrs.disabled as boolean)"
					:loading="($attrs.disabled as boolean)"
				>
					<el-icon>
						<Upload />
					</el-icon>
					{{ $attrs.disabled ? '正在上传中' : text || '上传文件' }}
				</el-button>
				<el-link
					v-else
					style="height: 32px"
					type="primary"
					:underline="false"
					:disabled="($attrs.disabled as boolean)"
					:loading="($attrs.disabled as boolean)"
				>
					<el-icon>
						<Plus />
					</el-icon>
					{{ $attrs.disabled ? '正在上传中' : text || '上传文件' }}
				</el-link>
			</template>
			<template
				v-if="$attrs&&($attrs!['list-type']==='picture-card')"
				#file="{ file }"
			>
				<div>
					<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
					<span class="el-upload-list__item-actions">
						<span class="x-item-icon" @click="handlePictureCardPreview(file)">
							<img class="x-look-icon" src="../images/look-icon.png" alt="" />
							查看
						</span>
						<span class="x-item-icon" @click="handleRemove(file)">
							<img
								class="x-delete-icon"
								src="../images/delete-icon.png"
								alt=""
							/>
							删除
						</span>
					</span>
				</div>
			</template>
			<template v-else #file="{ file }">
				<div class="flex-between">
					<div style="display: flex; align-items: center">
						<img
							style="width: 16px; height: 16px"
							:src="showIcon(file.name)"
							alt=""
						/>
						<span>{{ file.name }}</span>
					</div>
					<div>
						<el-link type="primary" @click="handleDownLoad(file)">下载</el-link>
						<el-link
							type="danger"
							style="margin-left: 16px"
							@click="handleRemove(file)"
						>
							删除
						</el-link>
					</div>
				</div>
			</template>
			<template #tip>
				<div style="color: #e6a23c; font-size: 12px" v-html="placeholder"></div>
				<div v-if="download">
					<el-link style="height: 32px" type="primary" @click="download()">
						<el-icon>
							<Download />
						</el-icon>
						模板下载
					</el-link>
				</div>
			</template>
		</el-upload>
		<el-progress
			v-if="progress && percentage > 0"
			style="width: 100%"
			:percentage="percentage"
		/>
		<div v-if="dialogVisible" class="x-view-box">
			<img :src="dialogImageUrl" alt="Preview Image" />
			<el-icon class="x-close-icon" @click="dialogVisible = false">
				<Close></Close>
			</el-icon>
		</div>
	</XConfigProvider>
</template>

<script setup lang="ts">
import XConfigProvider from '../XConfigProvider/index.vue'
import {ref,watch} from 'vue'
import {ElIcon,ElButton,ElLink,ElUpload,ElMessage} from 'element-plus'

import {
	UploadUserFile,
	UploadFile,
	UploadRawFile
} from 'element-plus';
import { PropType } from 'vue';
import { Plus, Close, Upload, Download } from '@element-plus/icons-vue';
import { typeEnum } from './typeEnum';

const emit = defineEmits(['update:modelValue','remove','check']);
const props = defineProps({
	modelValue: {
		type: Array as PropType<UploadUserFile[]>,
		default() {
			return [] as UploadUserFile[];
		}
	},
	// 上传控件是否为按钮
	isButton: {
		type: Boolean,
		default() {
			return false;
		}
	},
	// 上传文字
	text: {
		type: String,
		default() {
			return '';
		}
	},
	// 上传提示信息
	placeholder: {
		type: String,
		default() {
			return '';
		}
	},
	// 图片宽度
	width: {
		type: String,
		default() {
			return '';
		}
	},
	// 图片高度
	height: {
		type: String,
		default() {
			return '';
		}
	},
	// 文件大小
	size: {
		type: Number,
		default: 5 * 1024 * 1024
	},
	// 模板下载的func
	download: {
		type: Function,
		default: null
	},
	refForm: {
		type: Object as any,
		default() {
			return null;
		}
	},
	// 是否显示进度条
	progress: {
		type: Boolean,
		default() {
			return false;
		}
	}
});
const width = ref(props.width || '160px');
const height = ref(props.height || '104px');
// 文件列表list
const fileArray = ref(props.modelValue);

function beforeUpload(rawFile: UploadRawFile) {
	if (rawFile.size > props.size) {
		ElMessage.error(
			`${rawFile.name}文件大小不能超过${
				props.size / 1024 > 1024
					? `${props.size / 1024 / 1024}M`
					: `${props.size / 1024}kb`
			}`
		);
		return false;
	}
}
async function httpRequest(func: any, options: any) {
	if (func) {
		time = Math.ceil((options.file.size / (2 * 1024 * 1024) / 100) * 1000); // 按2M/s计算
		try {
			props.progress && startTimer();
			const result = await func(options, props.refForm);
			setTimeout(() => {
				getFileArray();
			}, 500);
			percentage.value = 100;
			setTimeout(() => {
				percentage.value = 0;
			}, 1000);
			return result;
		} catch {
			percentage.value = 0;
		} finally {
			clearTimeout(timer);
		}
	}
}

const dialogVisible = ref(false);
const dialogImageUrl = ref('');
const handlePictureCardPreview = (file: UploadFile) => {
	dialogImageUrl.value = file.url!;
	dialogVisible.value = true;
};
function showIcon(name: string) {
	const fileType = name.split('.').pop()?.toLocaleLowerCase();
	return new URL(
		`./images/${typeEnum[fileType as string] || 'txt'}.png`,
		import.meta.url
	).href;
}
async function handleDownLoad(
	file: UploadFile & { id: string; response: any }
) {
	if (!file.id) {
		return ElMessage.error('文件正在上传中,无法下载');
	}
	if(file.url){
		const a = document.createElement('a');
		a.href = file.url!;
		a.click();
		a.remove();
	}else{
		emit('check',file)
	}
}
async function handleRemove(file: UploadFile & { id: string; response: any }) {
	try{
		await emit('remove',file)
	}finally{
		fileArray.value = fileArray.value.filter((val: any) => {
			if (val.response) {
				val.id = val.response.id;
			}
			return val.id !== file.id;
		});
		emit('update:modelValue', fileArray.value);
	}
}

function getFileArray() {
	fileArray.value = fileArray.value.map((val: any) => {
		return {
			name: val.response?.name || val.name,
			id: val.response?.id || val.id,
			url: val.response?.imageUrl || val.response?.url || val.url
		};
	});
	emit('update:modelValue', fileArray.value);
}

// 进度条
const percentage = ref(0);
// 定时器间隔
let time = 0;
// 定时器id
let timer: any = null;
function startTimer() {
	timer = setTimeout(() => {
		if (percentage.value < 99) {
			percentage.value++;
			startTimer();
		}
	}, time);
}

watch(
	() => props.modelValue,
	() => {
		fileArray.value = props.modelValue;
	}
);
</script>

<style lang="scss" scoped>
.filelist {
	display: flex;
	justify-content: space-between;
	align-items: center;
}
:deep(.el-upload--picture-card) {
	width: v-bind(width);
	height: v-bind(height);
	border: none;
}
.x-avatar {
	width: v-bind(width) !important;
	height: v-bind(height);
	background-color: #fafafa;
	border: 1px dashed #cdd0d6;
	border-radius: 4px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	color: #999999;
}
.x-item-icon {
	display: flex;
	flex-direction: column;
	align-items: center;
	font-size: 12px;
	.x-look-icon {
		width: 20px;
	}
	.x-delete-icon {
		width: 16px;
	}
}
:deep(.el-upload-list) {
	margin: 0 !important;
}
:deep(.el-upload-list--picture-card .el-upload-list__item) {
	width: v-bind(width);
	height: v-bind(height);
	justify-content: center;
	align-items: center;
}
.x-view-box {
	background-color: rgba(0, 0, 0, 0.4);
	position: fixed;
	z-index: 999;
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	overflow: auto;
	text-align: center;
	img {
		margin-top: 100px;
	}
	.x-close-icon {
		position: absolute;
		right: 20px;
		top: 20px;
		font-size: 24px;
		color: #fff;
		cursor: pointer;
	}
}
.x-hiddeUpload :deep(.el-upload) {
	display: none !important;
}
</style>
